﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Xml.Serialization;
using zEngine;
using zEngine.GameObjs;
using zEngine.Cameras;
using FYP.Profilings;

namespace FYP.TestCases
{
    public class TestCase1 : TestCase
    {
        private List<zObject> _listObj;

        int maxCharacter = 1000;
        // Number of object in a round
        private int _noInRow = 40;

        private Texture2D _mainTexture;
        private Model _mainModel3D;

        private int _noOfVertices;
        private int _noOfPrimatives;

        private KeyboardControlCamera _mainCam;

        private SpriteFont _debugFont;


        #region Properties
        public KeyboardControlCamera MainCam
        {
            get { return _mainCam; }
            set { _mainCam = value; }
        }
        public Texture2D MainTexture
        {
            get { return _mainTexture; }
            set { _mainTexture = value; }
        }
        public Model MainModel3D
        {
            get { return _mainModel3D; }
            set { _mainModel3D = value; }
        }
        public List<zObject> ListObj
        {
            get { return _listObj; }
            set { _listObj = value; }
        }
        public int NoInRow
        {
            get { return _noInRow; }
            set { _noInRow = value; }
        }
        public SpriteFont DebugFont
        {
            get { return _debugFont; }
            set { _debugFont = value; }
        }
        public int NoOfVertices
        {
            get { return _noOfVertices; }
            set { _noOfVertices = value; }
        }
        public int NoOfPrimatives
        {
            get { return _noOfPrimatives; }
            set { _noOfPrimatives = value; }
        }
        #endregion

        /// <summary>
        /// Initializes a new instance of the TestCase1 class.
        /// </summary>
        public TestCase1(Game game, SpriteBatch sb) : base (game, sb)
        {
            TestcaseName = "Brute Force rendering profile without any techniques";
            DataFileOutput = "Data\\TestCase1.xml";

            Initialize();
            LoadContent();
        }

        public override void Initialize()
        {
            ListObj = new List<zObject>();

            MainCam = new KeyboardControlCamera(Game, new Vector3(0, 200, 200), Vector3.Zero);
            MainCam.FarPlane = 6000;

            base.Initialize();
        }

        public override void TestOn(GameTime gameTime)
        {
            base.TestOn(gameTime);
            MainCam.SetToMainCamera();
        }

        public override void LoadContent()
        {
            MainTexture = Game.Content.Load<Texture2D>("Characters\\casual02_m_25");
            MainModel3D = Game.Content.Load<Model>("characters\\cman2h");
            DebugFont = Game.Content.Load<SpriteFont>("Font\\debug");

            _noOfVertices = zModel.GetVerticesCount(MainModel3D);
            _noOfPrimatives = zModel.GetPrimativesCount(MainModel3D);

            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            MainCam.Update(gameTime);

            base.Update(gameTime);

            if (IsFinish) return;

            // If we finish 1 profilling add more characters. If hit the maximum, end the whole thing
            if (DataManager.CurrentData == null || DataManager.CurrentData.IsEnded)
            {
                // maximum character count then don't need to add a new one
                if (_listObj.Count >= maxCharacter)
                {
                    IsFinish = true;
                    return;
                }
                // Add 100 more characters
                for (int i = 0; i < 100; i++)
                {
                    AddMoreCharacter();
                }

                DataManager.AddNewData();
                // Set extra info for the new data profiling
                DataManager.CurrentData.SetStopTime(2000);
                DataManager.CurrentData.NoOfCharacters = _listObj.Count;
                DataManager.CurrentData.NoOfPoints = _listObj.Count * _noOfVertices;
                DataManager.CurrentData.NoOfTriangles = _listObj.Count * _noOfPrimatives;
                // Start profiling;
                DataManager.CurrentData.Start(gameTime);
            }
        }

        public override void Draw(GameTime gameTime)
        {
            for (int idx = 0; idx < ListObj.Count; idx++)
            {
                ListObj[idx].Draw(gameTime);
            }

            // Display statistic for on-screen profilling
            SpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);
            SpriteBatch.DrawString(DebugFont, this.TestcaseName, new Vector2(200, 20), Color.Yellow);
            SpriteBatch.DrawString(DebugFont, "No of characters : " + _listObj.Count.ToString(), new Vector2(40, 50), Color.White);
            SpriteBatch.End();

            base.Draw(gameTime);
        }

        // Add 1 more character in to our list objects
        public virtual zObject AddMoreCharacter()
        {
            // Prepare the new obj
            zObject newObj = new zObject(Game, MainModel3D, 100);
            newObj.Texture = MainTexture;

            // find the proper position
            newObj.Position = new Vector3(_listObj.Count % NoInRow * 100,
                0, _listObj.Count / NoInRow * 50);

            // Add to the list
            ListObj.Add(newObj);

            return newObj;
        }


    }
}
